/***************************************************************************
 *   Copyright (C) 2004 by cyril dupuit                                    *
 *   cyrildupuit@hotmail.com                                               *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

//*****************************************************************************
// Nom du module : RTC.c
// Description : Gestion de l'horloge temps reel
//*****************************************************************************
 
// Historique :
// 28/10/04 : Creation du module V1.0  

#include "Arch/Arch.h"
#include "Config.h"
#include "Lib/StdLib/time.h"
#include "Kernel/Thread.h"

//*****************************************************************************
// Variable externe :
//*****************************************************************************
//Tete du noyau
extern KernelHead_t Kernel;

//*****************************************************************************
// Definition des equivalences :
//*****************************************************************************
#define RTC_PIE 0x40		/* periodic interrupt enable */
#define RTC_AIE 0x20		/* alarm interrupt enable */
#define RTC_UIE 0x10		/* update-finished interrupt enable */

#define RTC_BATT_BAD 0x100	/* battery bad */
#define RTC_SQWE 0x08		/* enable square-wave output */
#define RTC_DM_BINARY 0x04	/* all time/date values are BCD if clear */
#define RTC_24H 0x02		/* 24 hour mode - else hours bit 7 means pm */
#define RTC_DST_EN 0x01	        /* auto switch DST - works f. USA only */

//*****************************************************************************
// But de la fonction : Lire l'heure de la RTC(Real Time Clock) et la stocker
// dans time
// Entree : Aucune
// Sortie :
//	pTime : Pointeur sur la structure de gestion du temps
// Parametre retourne : TRUE
//*****************************************************************************
Status_t ReadRtcTime(struct tm *pTime)
{
	//Attendre si la RTC est en cours de mise a jour
	if((CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) != 0) ThreadDelay(1);

	do
	{
		pTime->tm_sec = CMOS_READ(RTC_SECONDS);
		pTime->tm_min = CMOS_READ(RTC_MINUTES);
		pTime->tm_hour = CMOS_READ(RTC_HOURS);
		pTime->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH);
		pTime->tm_mon = CMOS_READ(RTC_MONTH);
		pTime->tm_year = CMOS_READ(RTC_YEAR);
	}
	while (pTime->tm_sec != CMOS_READ(RTC_SECONDS));

	if(!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)||RTC_ALWAYS_BCD)
	{
		BCD_TO_BIN(pTime->tm_sec);
		BCD_TO_BIN(pTime->tm_min);
		BCD_TO_BIN(pTime->tm_hour);
		BCD_TO_BIN(pTime->tm_mday);
		BCD_TO_BIN(pTime->tm_mon);
		BCD_TO_BIN(pTime->tm_year);
	}
	
	if((pTime->tm_year += 1900) < 1970) pTime->tm_year += 100;
	
	return TRUE;
}

//*****************************************************************************
// But de la fonction : Mettre a jour la RTC avec la nouvelle structure de
// gestion du temps
// Entree : 
//	pTime : Pointeur sur la structure a mettre a jour
// Parametre retourne : ERRor si un des parametres de temps est invalide,
// TRUE sinon
//*****************************************************************************
Status_t WriteRtcTime(struct tm *pTime)
{
	unsigned char mon, day, hrs, min, sec;
	unsigned char save_control, save_freq_select;
	unsigned int yrs;

	yrs = pTime->tm_year;
	mon = pTime->tm_mon;
	day = pTime->tm_mday;
	hrs = pTime->tm_hour;
	min = pTime->tm_min;
	sec = pTime->tm_sec;

	if(yrs > 255) return ERROR;

	if(yrs > 169) return ERROR;

	if(yrs >= 100) yrs -= 100;

	if(!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)|| RTC_ALWAYS_BCD)
	{
		BIN_TO_BCD(sec);
		BIN_TO_BCD(min);
		BIN_TO_BCD(hrs);
		BIN_TO_BCD(day);
		BIN_TO_BCD(mon);
		BIN_TO_BCD(yrs);
	}

	save_control = CMOS_READ(RTC_CONTROL);
	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);

	CMOS_WRITE(yrs, RTC_YEAR);
	CMOS_WRITE(mon, RTC_MONTH);
	CMOS_WRITE(day, RTC_DAY_OF_MONTH);
	CMOS_WRITE(hrs, RTC_HOURS);
	CMOS_WRITE(min, RTC_MINUTES);
	CMOS_WRITE(sec, RTC_SECONDS);

	CMOS_WRITE(save_control, RTC_CONTROL);
	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);

	return TRUE;
}

//*****************************************************************************
